// Keywords: QTL, quantitative trait loci, phenotypic competition

initialize() {
	defineConstant("optimum", 5.0);
	defineConstant("sigma_K", 1.0);
	defineConstant("sigma_C", 0.4);
	defineConstant("sigma_M", 0.5);
	defineConstant("NORM", dnorm(0.0, mean=0, sd=sigma_C));
	
	initializeSLiMOptions(dimensionality="x");
	initializeMutationRate(1e-6);
	initializeMutationType("m1", 0.5, "f", 0.0);        // neutral
	initializeMutationType("m2", 0.5, "n", 0.0, 1.0);   // QTL
	m2.convertToSubstitution = F;
	
	initializeGenomicElementType("g1", c(m1, m2), c(1, 0.01));
	initializeGenomicElement(g1, 0, 1e5 - 1);
	initializeRecombinationRate(1e-8);
	
	initializeInteractionType(1, "x", reciprocal=T, maxDistance=sigma_C * 3);     // competition
	i1.setInteractionFunction("n", 1.0, sigma_C);
	
	initializeInteractionType(2, "x", reciprocal=T, maxDistance=sigma_M * 3);     // mate choice
	i2.setInteractionFunction("n", 1.0, sigma_M);
}
mutationEffect(m2) { return 1.0; }
1 late() {
	sim.addSubpop("p1", 500);
	p1.setSpatialBounds(c(0.0, 10.0));
}
1: late() {
	inds = sim.subpopulations.individuals;
	
	// construct phenotypes and fitness effects from QTLs
	phenotypes = inds.sumOfMutationsOfType(m2);
	inds.fitnessScaling = 1.0 + dnorm(phenotypes, optimum, sigma_K);
	inds.x = phenotypes;
	
	// evaluate phenotypic competition
	i1.evaluate(p1);
	competition = sapply(inds, "sum(i1.strength(applyValue));");
	effects = 1.0 - competition / size(inds);
	inds.fitnessScaling = inds.fitnessScaling * effects;
}
2: first() {
	// evaluate mate choice in preparation for reproduction
	i2.evaluate(p1);
}
mateChoice() {
	// spatial mate choice
	return i2.strength(individual);
}
1:2001 late() {
	if (sim.cycle == 1)
		cat("  cyc    mean      sd\n");
	
	if (sim.cycle % 100 == 1)
	{
		phenotypes = p1.individuals.x;
		cat(format("%5d  ", sim.cycle));
		cat(format("%6.2f  ", mean(phenotypes)));
		cat(format("%6.2f\n", sd(phenotypes)));
	}
}
